﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace HttpService
{
	/// <summary>
	/// http error code
	/// </summary>
	public enum HttpReturnCode
	{
		OK = 200,
		NotFound = 404,
		Error = 500,
	}


	/// <summary>
	/// http response
	/// </summary>
	public class Response
	{
		Dictionary<string, string> Headers = new Dictionary<string, string>();
		//public Stream OutStream;
		public HttpReturnCode ReturnCode = HttpReturnCode.OK;
		bool isend = false;
		List<byte[]> contents = new List<byte[]>();
		int write_bytes_count;
		int content_bytes_count;
		public string HttpVersion = "HTTP/1.1";
		Socket Socket;
		string desc;


		public Response(Socket socket)
		{
			Socket = socket;
			desc = socket.RemoteEndPoint.ToString();
		}

        /// <summary>
        /// add http header item to http response header.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
		public void AddHeader(string key, string value)
		{
			if (Headers.ContainsKey(key))
				Headers[key] = value;
			else
				Headers.Add(key, value);
		}

        /// <summary>
        /// write string to http stream(html)
        /// </summary>
        /// <param name="text">string for html output</param>
		public void Write(string text)
		{
			byte[] bs = Encoding.UTF8.GetBytes(text);
			contents.Add(bs);
			content_bytes_count += bs.Length;
		}

        /// <summary>
        /// write byte[] to http stream. example jpeg,ico,gif...
        /// </summary>
        /// <param name="data">binary data for http stream</param>
		public void Write(byte[] data)
		{
			contents.Add(data);
			content_bytes_count += data.Length;
		}

		void WriteInter(string text)
		{
			byte[] bs = Encoding.UTF8.GetBytes(text);
			try
			{
				Socket.Send(bs, 0, bs.Length, SocketFlags.None);
				write_bytes_count += bs.Length;
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
		}


		/// <summary>
		/// end for http stream output, once call.
		/// </summary>
		public void End()
		{
			if (isend) return;
			if (!Socket.Connected) return;

			WriteInter(HttpVersion + " " + (int)ReturnCode + " " + ReturnCode.ToString() + "\r\n");
			if (!Headers.ContainsKey("Content-Type"))
				AddHeader("Content-Type", "text/html; charset=utf-8");
			foreach (var iter in Headers)
			{
				if (iter.Value == null || iter.Value == "")
					WriteInter(iter.Key + "\r\n");
				else
					WriteInter(iter.Key + ":" + iter.Value + "\r\n");
			}

			WriteInter("Content-Length:" + content_bytes_count + "\r\n\r\n");

			try
			{
				foreach (byte[] str in contents)
				{
					Socket.Send(str, 0, str.Length, SocketFlags.None);
				}
				//OutStream.Flush();
				isend = true;
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
			//OutStream.Close();
			Socket.Close();
		}
	}
}
